24. Exercise: Button States and SnackBar

L6 49 Button States SC

L6 50 Snackbar SC

Update:
In the video above, the sleepTrackerViewModel.showSnackBarEvent.observe() function in the SleepTrackerFragment.kt file, :

  • the first argument should be viewLifecycleOwner instead of the current object this.
  • The activity!!.findViewById(android.R.id.content) has been updated to requireActivity().findViewById(android.R.id.content).

Now it's your turn to complete this exercise yourself.

In this step, you'll add states to show and hide the buttons, and use a SnackBar to notify the user when they clear the data.

Button States

  1. Open fragment_sleep_tracker.xml.

  2. Add the enabled property to each button, and give it the value of a state variable:

 android:enabled="@{sleepTrackerViewModel.startButtonVisible}" 
 android:enabled="@{sleepTrackerViewModel.stopButtonVisible}" 
 android:enabled="@{sleepTrackerViewModel.clearButtonVisible}"
  1. Open SleepTrackerViewModel.kt and create three corresponding variables.

    Assign them a Transformations that tests it against the value of tonight.

    The START button should be visible when tonight is null, the STOP button when tonight is not null, and the CLEAR button if nights contains any nights:

val startButtonVisible = Transformations.map(tonight) {
   null == it
}
val stopButtonVisible = Transformations.map(tonight) {
   null != it
}
val clearButtonVisible = Transformations.map(nights) {
   it?.isNotEmpty()
}
  1. Run your app, and that's all there is to it!

Snackbar

Use the same pattern as for navigation to set up and trigger a snackbar when the data is cleared.

  1. In the SleepTrackerViewModel, create the encapsulated event:
 private var _showSnackbarEvent = MutableLiveData<Boolean>()

 val showSnackBarEvent: LiveData<Boolean>
      get() = _showSnackbarEvent
  1. Then implement doneShowingSnackbar():
 fun doneShowingSnackbar() {
   _showSnackbarEvent.value = false
}
  1. In the SleepTrackerFragment, add an observer:
sleepTrackerViewModel.showSnackBarEvent.observe(viewLifecycleOwner, Observer { })
  1. Display the snackbar and immediately reset the event:
   if (it == true) { // Observed state is true.
       Snackbar.make(
               requireActivity().findViewById(android.R.id.content),
               getString(R.string.cleared_message),
               Snackbar.LENGTH_SHORT // How long to display the message.
       ).show()
       sleepTrackerViewModel.doneShowingSnackbar()
   }
  1. To trigger the event, in onClear(), set the event value to true:
_showSnackbarEvent.value = true
  1. Build and run your app!

If you want to start at this step, you can download this exercise from: Step.07-Exercise-Add-Button-States-and-SnackBar.

You will find plenty of //TODO comments to help you complete this exercise, and if you get stuck, go back and watch the video again.

Once you’re done, you can check your solution against the solution we’ve provided here: Step.07-Add-Button-States-and-SnackBar, or using this git diff.

Task List:

Task Feedback:

Congratulations! This lesson introduced coroutines and other more advanced topics, and you've completed it all.